package com.dailywork.basepro.stroper;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author think
 * @version 1.0.0 IP地址复原
 * @since 2020/4/21
 */
public class IPDec {
    public static void main(String[] args) {
        System.out.println(StringUtils.join(restoreIpAddresses1("552552689")));
        System.out.println(StringUtils.join(restoreIpAddresses2("552552689")));
    }

    public static List<String> restoreIpAddresses1(String s) {
        int len = s.length();
        List<String> res = new ArrayList<>();
        if (len > 12 || len < 4) {
            return res;
        }

        Deque<String> path = new ArrayDeque<>(4);
        dfs(s, len, 0, 4, path, res);
        return res;
    }

    // 需要一个变量记录剩余多少段还没被分割
    private static void dfs(String s, int len, int begin, int residue, Deque<String> path, List<String> res) {
        if (begin == len) {
            if (residue == 0) {
                res.add(String.join(".", path));
            }
            return;
        }

        for (int i = begin; i < begin + 3; i++) {
            if (i >= len) {
                break;
            }

            if (residue * 3 < len - i) {
                continue;
            }

            if (judgeIpSegment(s, begin, i)) {
                String currentIpSegment = s.substring(begin, i + 1);
                path.addLast(currentIpSegment);
                dfs(s, len, i + 1, residue - 1, path, res);
                path.removeLast();
            }
        }
    }

    private static boolean judgeIpSegment(String s, int left, int right) {
        int len = right - left + 1;
        if (len > 1 && s.charAt(left) == '0') {
            return false;
        }
        int res = 0;
        while (left <= right) {
            res = res * 10 + s.charAt(left) - '0';
            left++;
        }
        return res >= 0 && res <= 255;
    }

    public static List<String> restoreIpAddresses2(String s) {
        List<String> res = partition(s, 4);
        return res.stream().map(s1 -> s1.substring(0, s1.length() - 1)).collect(Collectors.toList());
    }

    // count代表需要得到几组数字
    private static List<String> partition(String s, int count) {
        List<String> res = new ArrayList<>();
        if (s.isEmpty() && count == 0) {
            res.add("");
            return res;
        }
        // ip地址最多可选择三位，最少可选择一位
        if (count > s.length() || count < s.length() / 3) {
            return res;
        }

        for (int i = 0; i < 3 && i < s.length(); i++) {
            if (!isValidIp(s.substring(0, i + 1))) {
                continue;
            }
            List<String> temp = partition(s.substring(i + 1), count - 1);
            for (String right : temp) {
                res.add(s.substring(0, i + 1) + "." + right);
            }
        }
        return res;
    }

    private static boolean isValidIp(String s) {
        if (s.startsWith("0")) {
            return s.equals("0");
        }
        int ip = Integer.parseInt(s);
        return ip >= 0 && ip <= 255;
    }
}
